package com.tripspins.app.helper;


import android.content.Context;
import android.database.sqlite.SQLiteDatabase;
import android.os.AsyncTask;
import android.widget.Toast;

import com.tripspins.app.R;
import com.tripspins.app.bo.Attachment;
import com.tripspins.app.bo.Pin;
import com.tripspins.app.bo.Trip;
import com.tripspins.app.bo.User;
import com.tripspins.app.dao.AttachmentDAO;
import com.tripspins.app.dao.TripDAO;
import com.tripspins.app.dao.UserDAO;

import org.apache.http.client.ClientProtocolException;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;

import java.io.BufferedReader;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.UnsupportedEncodingException;

import ch.boye.httpclientandroidlib.HttpEntity;
import ch.boye.httpclientandroidlib.HttpResponse;
import ch.boye.httpclientandroidlib.client.HttpClient;
import ch.boye.httpclientandroidlib.client.methods.HttpPost;
import ch.boye.httpclientandroidlib.entity.StringEntity;
import ch.boye.httpclientandroidlib.entity.mime.HttpMultipartMode;
import ch.boye.httpclientandroidlib.entity.mime.MultipartEntityBuilder;
import ch.boye.httpclientandroidlib.entity.mime.content.FileBody;
import ch.boye.httpclientandroidlib.impl.client.DefaultHttpClient;


/**
 * Created by joaortk on 24/02/14.
 */
public class SyncHelper {

    private Trip trip;
    private User user;
    private Context context;
//    private static User user;

    public void sync(Trip trip, Context context, User user)
    {
        this.user = user;
        this.trip = trip;
        this.context = context;
        DoPost post = new DoPost(context);
        String url = context.getResources().getString(R.string.WS_ADDRESS_TRIPS)
                + "?id_facebook="
                + user.getFacebookId()
                + "txt_token="
                + user.getToken();
        JSONObject json = tripToJson(trip);
        post.execute(new Object[]{json.toString(),url});
    }

    public void sync(User user, Context context)
    {
        this.user = user;
        this.context = context;
        DoPost post = new DoPost(context);
        String url = context.getResources().getString(R.string.WS_ADDRESS_USERS);
        JSONObject json = userToJson(user);
        post.execute(new Object[]{json.toString(),url});
    }

    public void sync(long tripId, long pinId, long attachmentId, File file, Context context, User user)
    {
        this.user = user;
        DoSendFile sendFile = new DoSendFile(context);
        String url = context.getResources().getString(R.string.WS_ADDRESS_ATTACHMENT)+ "?id_facebook="
                + user.getFacebookId()
                + "txt_token="
                + user.getToken();
        sendFile.execute(new Object[]{tripId, pinId, attachmentId, file, url});
    }



    private JSONObject tripToJson(Trip t)
    {
        JSONObject jsonTrip = new JSONObject();
        JSONObject jsonPin = null;
        JSONArray jsonListPins = null;
        JSONObject jsonAttachment = null;
        JSONArray jsonListAttachments = null;
        JSONObject jsonWeather = null;
        JSONObject jsonAddress = null;
        JSONObject jsonContact = null;

        try {

            jsonTrip.accumulate("txt_title", t.getDescription());
            jsonTrip.accumulate("txt_status", t.getStatus().getValue());
            jsonListPins = new JSONArray();
            for(Pin p : t.getPins())
            {
                jsonPin = new JSONObject();
                jsonPin.accumulate("_id",p.getId());
                jsonPin.accumulate("id_trip",t.getIdOnServer());
                jsonPin.accumulate("dt_pin",p.getDateFormatted("yyyy-MM-dd HH:mm:ss"));
                jsonPin.accumulate("num_latitude",p.getLatitude());
                jsonPin.accumulate("num_longitude",p.getLongitude());
                jsonPin.accumulate("txt_note",p.getTextNote());
                jsonPin.accumulate("txt_title",p.getTitle());
                jsonWeather = new JSONObject();
                if(p.getCurrentWeather() != null)
                {
                    jsonWeather.accumulate("_id",p.getId());
                    jsonWeather.accumulate("id_pin",p.getId());
                    jsonWeather.accumulate("num_cloud_cover",p.getCurrentWeather().getCloudCover());
                    jsonWeather.accumulate("num_humidity",p.getCurrentWeather().getHumidity());
                    jsonWeather.accumulate("num_precipitation_mm",p.getCurrentWeather().getPrecipMM());
                    jsonWeather.accumulate("num_pressure",p.getCurrentWeather().getPressure());
                    jsonWeather.accumulate("num_temp_c",p.getCurrentWeather().getTempC());
                    jsonWeather.accumulate("num_temp_f",p.getCurrentWeather().getTempF());
                    jsonWeather.accumulate("num_visibility",p.getCurrentWeather().getVisibility());
                    jsonWeather.accumulate("txt_wind_dir_16point",p.getCurrentWeather().getWindDir16Point());
                    jsonWeather.accumulate("txt_wind_dir_degree",p.getCurrentWeather().getWindDirDegree());
                    jsonWeather.accumulate("num_wind_speed_kmph",p.getCurrentWeather().getWindSpeedKmph());
                    jsonWeather.accumulate("num_wind_speed_mph",p.getCurrentWeather().getWindspeedMiles());
                    jsonWeather.accumulate("txt_description",p.getCurrentWeather().getWeatherDesc());
                    jsonWeather.accumulate("txt_icon_url",p.getCurrentWeather().getWeatherIconUrl());
                    jsonPin.accumulate("weather",jsonWeather);
                }

                jsonAddress = new JSONObject();
                if(p.getAddress() != null && p.getAddress().getCountryName() != null)
                {
                    jsonAddress.accumulate("_id",p.getId());
                    jsonAddress.accumulate("id_pin",p.getId());
                    jsonAddress.accumulate("txt_country",p.getAddress().getCountryName());
                    jsonAddress.accumulate("txt_state",p.getAddress().getAdminArea());
                    jsonAddress.accumulate("txt_city",p.getAddress().getSubLocality());
                    jsonAddress.accumulate("txt_street",p.getAddress().getThoroughfare());
                    jsonAddress.accumulate("num_umber",p.getAddress().getSubThoroughfare());
                    jsonPin.accumulate("address",jsonAddress);
                }

                jsonListAttachments = new JSONArray();
                for(Attachment att : p.getAttachments())
                {
                    jsonAttachment = new JSONObject();
                    jsonAttachment.accumulate("_id",att.getId());
                    jsonAttachment.accumulate("id_pin",p.getId());
                    jsonAttachment.accumulate("txt_file_path",att.getPath());
                    jsonAttachment.accumulate("txt_file_path_thumbnail",att.getThumbnailPath());
                    jsonAttachment.accumulate("id_attachment_type",att.getFileType().getValue());
                    jsonAttachment.accumulate("dt_attachment",p.getDateFormatted());
                    if(att.getContact() != null)
                    {
                        jsonContact = new JSONObject();
                        jsonContact.accumulate("_id",att.getId());//passa ID do attachment
                        jsonContact.accumulate("txt_name",att.getContact().getName());
                        jsonContact.accumulate("txt_email",att.getContact().getEmail());
                        jsonContact.accumulate("txt_source",att.getContact().getContactSource());
                        jsonContact.accumulate("txt_id_on_source",att.getContact().getContactIdOnSource());
                        jsonContact.accumulate("txt_picture_path",att.getContact().getPicturePath());
                        jsonContact.accumulate("txt_thumbnail_path",att.getContact().getPictureThumbnailPath());
                        jsonContact.accumulate("txt_phone_number",att.getContact().getPictureThumbnailPath());
                        jsonAttachment.accumulate("contact",jsonContact);
                    }
                    jsonListAttachments.put(jsonAttachment);
                }
                if(jsonListAttachments.length() > 0)
                    jsonPin.accumulate("attachments",jsonListAttachments);

                jsonListPins.put(jsonPin);
            }
            jsonTrip.accumulate("pins",jsonListPins);
        } catch (JSONException e) {
            e.printStackTrace();
        }
        return jsonTrip;

    }

    private JSONObject userToJson(User u)
    {
        JSONObject jsonUser = new JSONObject();

        try {

            jsonUser.accumulate("txt_name", u.getName());
            jsonUser.accumulate("id_facebook", u.getFacebookId());

        } catch (JSONException e) {
            e.printStackTrace();
        }
        return jsonUser;

    }

    class DoPost extends AsyncTask<Object, Void, String>
    {
        Context context;
        public DoPost(Context context) {
            this.context = context;
        }

        @Override
        protected String doInBackground(Object... objects)
        {
            String result = null;

            try{
                String json = objects[0].toString();//JsonObject
                String url = objects[1].toString(); // ws URL
                HttpClient httpclient = new DefaultHttpClient();
                HttpPost httpPost = new HttpPost(url);
                httpPost.setEntity(new StringEntity(json));
                httpPost.setHeader("Accept", "application/json");
                httpPost.setHeader("Content-type", "application/json");
                HttpResponse httpResponse = httpclient.execute(httpPost);
                InputStream inputStream = httpResponse.getEntity().getContent();
                result = convertInputStreamToString(inputStream);


            } catch (ClientProtocolException e) {
                e.printStackTrace();
            } catch (UnsupportedEncodingException e) {
                e.printStackTrace();
            } catch (IOException e) {
                e.printStackTrace();
            }

            return result;
        }

        @Override
        protected void onPostExecute(String s) {
            super.onPostExecute(s);
            if(s == null) return;
            DbHelper dbHelper = new DbHelper(context);
            SQLiteDatabase database = dbHelper.getWritableDatabase();
            JSONObject jsonResponse = new JSONObject();
            try {
                jsonResponse = new JSONObject(s);
            } catch (JSONException e) {
                try {
                    jsonResponse = new JSONObject(s.substring(2));

                } catch(JSONException e2){
                    e2.printStackTrace();
                }
            }


            try {
                if (trip != null)
                {
                    trip.setIdOnServer(Long.parseLong(jsonResponse.getString("_id")));
                    TripDAO tripDAO = new TripDAO(database);
                    tripDAO.updateSyncedTrip(trip);
                    UserDAO userDAO = new UserDAO(database);
                    SyncHelper syncHelper = new SyncHelper();
                    for (Trip trip : tripDAO.getTripsSynced(userDAO.getLoggedUser().getId())) {
                        for (Pin pin : trip.getPins()) {
                            for (Attachment attachment : pin.getAttachmentsToSync()) {
                                File toSync = new File(attachment.getPath());
                                if (toSync.exists()) {
                                    syncHelper.sync(trip.getIdOnServer()
                                            , pin.getId()
                                            , attachment.getId()
                                            , toSync
                                            , context
                                            , user
                                    );
                                }
                            }
                        }
                    }
                }
                else if (user != null)
                {
                    user.setIdOnServer(Long.parseLong(jsonResponse.getString("_id")));
                    user.setToken(jsonResponse.getString("txt_token"));
                    UserDAO userDAO = new UserDAO(database);
                    userDAO.persist(user);
                    TripDAO tripDAO = new TripDAO(database);
                    tripDAO.updateUser(user);
                }
            }
            catch(Exception ex){}

        }

        private String convertInputStreamToString(InputStream inputStream) throws IOException {
            BufferedReader bufferedReader = new BufferedReader( new InputStreamReader(inputStream));
            String line = "";
            String result = "";
            while((line = bufferedReader.readLine()) != null)
                result += line;

            inputStream.close();
            return result;

        }
    }

    class DoSendFile extends AsyncTask<Object, Void, String>
    {
        Context context;
        public DoSendFile(Context context) {
            this.context = context;
        }


            @Override
            protected String doInBackground(Object... objects)
            {
                String result = null;

                try{
                    long tripId = (Long)objects[0];
                    long pinId = (Long)objects[1];
                    long attachmentId = (Long)objects[2];
                    File file = (File)objects[3];
                    String strUrl = objects[4].toString();

                    HttpClient httpclient = new DefaultHttpClient();
                    HttpPost httpPost = new HttpPost(strUrl);


                    MultipartEntityBuilder builder = MultipartEntityBuilder.create();
                    builder.setMode(HttpMultipartMode.BROWSER_COMPATIBLE);
                    FileBody fileBody = new FileBody(file);

                    builder.addPart("upFile",fileBody);
                    HttpEntity entity = builder.build();
                    httpPost.setEntity(entity);
                    httpPost.addHeader("id_trip", String.valueOf(tripId));
                    httpPost.addHeader("id_pin", String.valueOf(pinId));
                    httpPost.addHeader("id_attachment", String.valueOf(attachmentId));
                    httpPost.addHeader("file_name", file.getName());


                    HttpResponse httpResponse = httpclient.execute(httpPost);
                    InputStream inputStream = httpResponse.getEntity().getContent();
                    result = convertInputStreamToString(inputStream);


                } catch (ClientProtocolException e) {
                    e.printStackTrace();
                } catch (UnsupportedEncodingException e) {
                    e.printStackTrace();
                } catch (IOException e) {
                    e.printStackTrace();
                }


                return result;

            }

        @Override
        protected void onPostExecute(String s) {
            super.onPostExecute(s);
            long pinId;
            long attachmentId;

            JSONObject jsonResponse = null;
            try {
                jsonResponse = new JSONObject(s.substring(2));
                pinId = jsonResponse.getLong("id_pin");
                attachmentId = jsonResponse.getLong("_id");

            } catch (JSONException e) {
                try{
                    jsonResponse = new JSONObject(s);
                    pinId = jsonResponse.getLong("id_pin");
                    attachmentId = jsonResponse.getLong("_id");

                }

                catch (JSONException e2) {
                    e.printStackTrace();
                    Toast.makeText(context,context.getString(R.string.warning_fail_send_file),Toast.LENGTH_SHORT).show();
                    return;
                }
            }
            DbHelper dbHelper = new DbHelper(context);
            SQLiteDatabase database = dbHelper.getWritableDatabase();
            AttachmentDAO attachmentDAO = new AttachmentDAO(database);
            attachmentDAO.updateSyncedFile(pinId,attachmentId);


        }

        private String convertInputStreamToString(InputStream inputStream) throws IOException {
            BufferedReader bufferedReader = new BufferedReader( new InputStreamReader(inputStream));
            String line = "";
            String result = "";
            while((line = bufferedReader.readLine()) != null)
                result += line;

            inputStream.close();
            return result;

        }
    }



}

